5300 #include "types.h"
5301 #include "param.h"
5302 #include "mmu.h"
5303 #include "proc.h"
5304 #include "defs.h"
5305 #include "x86.h"
5306 #include "elf.h"
5307 
5308 int
5309 exec(char *path, char **argv)
5310 {
5311   char *mem, *s, *last;
5312   int i, argc, arglen, len, off;
5313   uint sz, sp, spbottom, argp;
5314   struct elfhdr elf;
5315   struct inode *ip;
5316   struct proghdr ph;
5317   pde_t *pgdir, *oldpgdir;
5318 
5319   pgdir = 0;
5320   sz = 0;
5321 
5322   if((ip = namei(path)) == 0)
5323     return -1;
5324   ilock(ip);
5325 
5326   // Check ELF header
5327   if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
5328     goto bad;
5329   if(elf.magic != ELF_MAGIC)
5330     goto bad;
5331 
5332   if(!(pgdir = setupkvm()))
5333     goto bad;
5334 
5335   // Load program into memory.
5336   for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
5337     if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
5338       goto bad;
5339     if(ph.type != ELF_PROG_LOAD)
5340       continue;
5341     if(ph.memsz < ph.filesz)
5342       goto bad;
5343     if(!(sz = allocuvm(pgdir, sz, ph.va + ph.memsz)))
5344       goto bad;
5345     if(!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz))
5346       goto bad;
5347   }
5348   iunlockput(ip);
5349 
5350   // Allocate and initialize stack at sz
5351   sz = spbottom = PGROUNDUP(sz);
5352   if(!(sz = allocuvm(pgdir, sz, sz + PGSIZE)))
5353     goto bad;
5354   mem = uva2ka(pgdir, (char *)spbottom);
5355 
5356   arglen = 0;
5357   for(argc=0; argv[argc]; argc++)
5358     arglen += strlen(argv[argc]) + 1;
5359   arglen = (arglen+3) & ~3;
5360 
5361   sp = sz;
5362   argp = sz - arglen - 4*(argc+1);
5363 
5364   // Copy argv strings and pointers to stack.
5365   *(uint*)(mem+argp-spbottom + 4*argc) = 0;  // argv[argc]
5366   for(i=argc-1; i>=0; i--){
5367     len = strlen(argv[i]) + 1;
5368     sp -= len;
5369     memmove(mem+sp-spbottom, argv[i], len);
5370     *(uint*)(mem+argp-spbottom + 4*i) = sp;  // argv[i]
5371   }
5372 
5373   // Stack frame for main(argc, argv), below arguments.
5374   sp = argp;
5375   sp -= 4;
5376   *(uint*)(mem+sp-spbottom) = argp;
5377   sp -= 4;
5378   *(uint*)(mem+sp-spbottom) = argc;
5379   sp -= 4;
5380   *(uint*)(mem+sp-spbottom) = 0xffffffff;   // fake return pc
5381 
5382   // Save program name for debugging.
5383   for(last=s=path; *s; s++)
5384     if(*s == '/')
5385       last = s+1;
5386   safestrcpy(proc->name, last, sizeof(proc->name));
5387 
5388   // Commit to the user image.
5389   oldpgdir = proc->pgdir;
5390   proc->pgdir = pgdir;
5391   proc->sz = sz;
5392   proc->tf->eip = elf.entry;  // main
5393   proc->tf->esp = sp;
5394 
5395   switchuvm(proc);
5396 
5397   freevm(oldpgdir);
5398 
5399   return 0;
5400  bad:
5401   if(pgdir) freevm(pgdir);
5402   iunlockput(ip);
5403   return -1;
5404 }
5405 
5406 
5407 
5408 
5409 
5410 
5411 
5412 
5413 
5414 
5415 
5416 
5417 
5418 
5419 
5420 
5421 
5422 
5423 
5424 
5425 
5426 
5427 
5428 
5429 
5430 
5431 
5432 
5433 
5434 
5435 
5436 
5437 
5438 
5439 
5440 
5441 
5442 
5443 
5444 
5445 
5446 
5447 
5448 
5449 
